import psutil
import time
import json
from datetime import datetime


class DeviceDynamicCollector(object):
    """设备动态信息采集器"""

    def __init__(self):
        self.dynamic_info_map = {}
        # 用于计算变化率的历史数据
        self._prev_stats = {
            'cpu': None,
            'network': None,
            'disk': None,
            'timestamp': None
        }

    def _calculate_rate(self, current_val, prev_val, dt):
        """计算变化率"""
        if prev_val is None or dt <= 0:
            return None
        return (current_val - prev_val) / dt

    def get_cpu_dynamic_info(self, timestamp=None):
        """获取CPU动态信息"""
        if timestamp is None:
            timestamp = time.time()

        # 基础信息
        basic_info = {
            "physical_cores": psutil.cpu_count(logical=False),  # 物理核心数
            "logical_cores": psutil.cpu_count(logical=True),  # 逻辑核心数
        }

        # CPU使用率信息
        usage_info = {
            "cpu_percent": psutil.cpu_percent(interval=0.1),  # 总体CPU使用率
            "cpu_percent_per_core": psutil.cpu_percent(interval=0.1, percpu=True),  # 每核心使用率
            "load_average": list(psutil.getloadavg()) if hasattr(psutil, 'getloadavg') else None,  # 系统负载
        }

        # CPU时间信息
        cpu_times = psutil.cpu_times()
        cpu_times_percent = psutil.cpu_times_percent(interval=0.1)

        times_info = {
            "user": cpu_times.user,  # 用户态时间
            "system": cpu_times.system,  # 内核态时间
            "idle": cpu_times.idle,  # 空闲时间
            "nice": getattr(cpu_times, 'nice', 0),  # nice时间
            "iowait": getattr(cpu_times, 'iowait', 0),  # IO等待时间
            "irq": getattr(cpu_times, 'irq', 0),  # 硬中断时间
            "softirq": getattr(cpu_times, 'softirq', 0),  # 软中断时间
            "steal": getattr(cpu_times, 'steal', 0),  # 虚拟化steal时间
        }

        times_percent_info = {
            "user_percent": cpu_times_percent.user,  # 用户态时间百分比
            "system_percent": cpu_times_percent.system,  # 内核态时间百分比
            "idle_percent": cpu_times_percent.idle,  # 空闲时间百分比
            "nice_percent": getattr(cpu_times_percent, 'nice', 0),
            "iowait_percent": getattr(cpu_times_percent, 'iowait', 0),
            "irq_percent": getattr(cpu_times_percent, 'irq', 0),
            "softirq_percent": getattr(cpu_times_percent, 'softirq', 0),
            "steal_percent": getattr(cpu_times_percent, 'steal', 0),
        }

        # CPU频率信息
        freq_info = self._get_cpu_frequency_info()

        # CPU统计信息（包含变化率）
        stats_info = self._get_cpu_stats_info(timestamp)

        cpu_info = {
            "basic": basic_info,
            "usage": usage_info,
            "times": times_info,
            "times_percent": times_percent_info,
            "frequency": freq_info,
            "stats": stats_info,
        }

        self.dynamic_info_map['cpu'] = cpu_info

    def _get_cpu_frequency_info(self):
        """获取CPU频率信息"""
        try:
            freq = psutil.cpu_freq()
            freq_info = {
                "current": freq.current if freq else None,  # 当前频率(MHz)
                "min": freq.min if freq else None,  # 最小频率(MHz)
                "max": freq.max if freq else None  # 最大频率(MHz)
            }

            return freq_info
        except:
            return {"current": None, "min": None, "max": None}

    def _get_cpu_stats_info(self, timestamp):
        """获取CPU统计信息，包含变化率"""
        try:
            stats = psutil.cpu_stats()
            current_stats = {
                "ctx_switches": stats.ctx_switches,  # 上下文切换次数
                "interrupts": stats.interrupts,  # 中断次数
                "soft_interrupts": stats.soft_interrupts,  # 软中断次数
                "syscalls": getattr(stats, 'syscalls', 0),  # 系统调用次数
            }

            # 计算变化率
            rates = {}
            if (self._prev_stats['cpu'] and self._prev_stats['timestamp'] and
                    timestamp > self._prev_stats['timestamp']):
                dt = timestamp - self._prev_stats['timestamp']
                prev_cpu = self._prev_stats['cpu']

                rates = {
                    "ctx_switches_per_sec": self._calculate_rate(
                        current_stats["ctx_switches"], prev_cpu["ctx_switches"], dt
                    ),
                    "interrupts_per_sec": self._calculate_rate(
                        current_stats["interrupts"], prev_cpu["interrupts"], dt
                    ),
                    "soft_interrupts_per_sec": self._calculate_rate(
                        current_stats["soft_interrupts"], prev_cpu["soft_interrupts"], dt
                    ),
                    "syscalls_per_sec": self._calculate_rate(
                        current_stats["syscalls"], prev_cpu["syscalls"], dt
                    ),
                }

            # 更新历史数据
            self._prev_stats['cpu'] = current_stats.copy()

            return {
                "cumulative": current_stats,  # 累计值
                "rates": rates,  # 变化率(/s)
            }

        except Exception:
            return {
                "cumulative": {"ctx_switches": None, "interrupts": None, "soft_interrupts": None, "syscalls": None},
                "rates": {}
            }

    def get_memory_dynamic_info(self):
        """获取内存动态信息"""
        # 虚拟内存信息
        virtual_mem = psutil.virtual_memory()
        virtual_info = {
            "total": virtual_mem.total,  # 总内存(bytes)
            "available": virtual_mem.available,  # 可用内存(bytes)
            "used": virtual_mem.used,  # 已用内存(bytes)
            "free": virtual_mem.free,  # 空闲内存(bytes)
            "percent": virtual_mem.percent,  # 使用百分比
            "active": getattr(virtual_mem, 'active', None),  # 活跃内存(bytes)
            "inactive": getattr(virtual_mem, 'inactive', None),  # 非活跃内存(bytes)
            "buffers": getattr(virtual_mem, 'buffers', None),  # 缓冲区(bytes)
            "cached": getattr(virtual_mem, 'cached', None),  # 缓存(bytes)
            "shared": getattr(virtual_mem, 'shared', None),  # 共享内存(bytes)
            "slab": getattr(virtual_mem, 'slab', None),  # Slab内存(bytes)
        }

        # 交换空间信息
        swap_mem = psutil.swap_memory()
        swap_info = {
            "total": swap_mem.total,  # 总交换空间(bytes)
            "used": swap_mem.used,  # 已用交换空间(bytes)
            "free": swap_mem.free,  # 空闲交换空间(bytes)
            "percent": swap_mem.percent,  # 交换空间使用百分比
            "sin": swap_mem.sin,  # 换入次数
            "sout": swap_mem.sout,  # 换出次数
        }

        memory_info = {
            "virtual": virtual_info,
            "swap": swap_info,
        }

        self.dynamic_info_map['memory'] = memory_info

    def get_disk_dynamic_info(self, timestamp=None):
        """获取磁盘动态信息 - 只监控整体使用情况"""
        if timestamp is None:
            timestamp = time.time()

        # 策略1：只监控根分区（最简单）
        disk_usage_summary = self._get_root_partition_usage()

        # 总体磁盘IO信息
        disk_io = psutil.disk_io_counters()
        if disk_io:
            current_io_stats = {
                "read_count": disk_io.read_count,  # 读操作次数
                "write_count": disk_io.write_count,  # 写操作次数
                "read_bytes": disk_io.read_bytes,  # 读取字节数
                "write_bytes": disk_io.write_bytes,  # 写入字节数
                "read_time": disk_io.read_time,  # 读取时间(ms)
                "write_time": disk_io.write_time,  # 写入时间(ms)
                "busy_time": getattr(disk_io, 'busy_time', None),  # 磁盘忙碌时间(ms)
            }

            # 计算IO变化率
            io_rates = {}
            if (self._prev_stats['disk'] and self._prev_stats['timestamp'] and
                    timestamp > self._prev_stats['timestamp']):
                dt = timestamp - self._prev_stats['timestamp']
                prev_disk = self._prev_stats['disk']

                read_bytes_per_sec = self._calculate_rate(
                    current_io_stats["read_bytes"], prev_disk["read_bytes"], dt
                )
                write_bytes_per_sec = self._calculate_rate(
                    current_io_stats["write_bytes"], prev_disk["write_bytes"], dt
                )

                io_rates = {
                    "read_iops": self._calculate_rate(  # 读IOPS
                        current_io_stats["read_count"], prev_disk["read_count"], dt
                    ),
                    "write_iops": self._calculate_rate(  # 写IOPS
                        current_io_stats["write_count"], prev_disk["write_count"], dt
                    ),
                    "read_bytes_per_sec": read_bytes_per_sec,  # 读速度(bytes/s)
                    "write_bytes_per_sec": write_bytes_per_sec,  # 写速度(bytes/s)
                    "read_speed_mbps": read_bytes_per_sec / 1024 / 1024 if read_bytes_per_sec else None,  # 读速度(MB/s)
                    "write_speed_mbps": write_bytes_per_sec / 1024 / 1024 if write_bytes_per_sec else None,  # 写速度(MB/s)
                }

            # 更新历史数据
            self._prev_stats['disk'] = current_io_stats.copy()

            io_info = {
                "cumulative": current_io_stats,  # 累计值
                "rates": io_rates,  # 变化率(/s)
            }
        else:
            io_info = {
                "cumulative": None,
                "rates": {}
            }

        disk_info = {
            "usage": disk_usage_summary,  # 磁盘空间使用情况
            "io": io_info,  # 磁盘IO性能信息
        }

        self.dynamic_info_map['disk'] = disk_info

    def _get_root_partition_usage(self):
        """策略1：只获取根分区使用情况（推荐）"""
        try:
            # 直接获取根目录的磁盘使用情况
            usage = psutil.disk_usage('/')
            return {
                "total_space": usage.total,
                "used_space": usage.used,
                "free_space": usage.free,
                "usage_percent": usage.percent,
            }
        except Exception:
            return {
                "total_space": None,
                "used_space": None,
                "free_space": None,
                "usage_percent": None,
            }

    def get_network_dynamic_info(self, timestamp=None):
        """获取网络动态信息 - 只监控总体使用情况"""
        if timestamp is None:
            timestamp = time.time()

        # 总体网络IO信息
        net_io = psutil.net_io_counters()
        if net_io:
            current_net_stats = {
                "bytes_sent": net_io.bytes_sent,  # 发送字节数
                "bytes_recv": net_io.bytes_recv,  # 接收字节数
                "packets_sent": net_io.packets_sent,  # 发送包数
                "packets_recv": net_io.packets_recv,  # 接收包数
                "errin": net_io.errin,  # 接收错误数
                "errout": net_io.errout,  # 发送错误数
                "dropin": net_io.dropin,  # 接收丢包数
                "dropout": net_io.dropout,  # 发送丢包数
            }

            # 计算网络变化率
            net_rates = {}
            if (self._prev_stats['network'] and self._prev_stats['timestamp'] and
                    timestamp > self._prev_stats['timestamp']):
                dt = timestamp - self._prev_stats['timestamp']
                prev_net = self._prev_stats['network']

                bytes_recv_per_sec = self._calculate_rate(
                    current_net_stats["bytes_recv"], prev_net["bytes_recv"], dt
                )
                bytes_sent_per_sec = self._calculate_rate(
                    current_net_stats["bytes_sent"], prev_net["bytes_sent"], dt
                )

                net_rates = {
                    "bytes_recv_per_sec": bytes_recv_per_sec,  # 接收速度(bytes/s)
                    "bytes_sent_per_sec": bytes_sent_per_sec,  # 发送速度(bytes/s)
                    "packets_recv_per_sec": self._calculate_rate(  # 接收包速度(packets/s)
                        current_net_stats["packets_recv"], prev_net["packets_recv"], dt
                    ),
                    "packets_sent_per_sec": self._calculate_rate(  # 发送包速度(packets/s)
                        current_net_stats["packets_sent"], prev_net["packets_sent"], dt
                    ),
                    "errin_per_sec": self._calculate_rate(  # 接收错误速度(errors/s)
                        current_net_stats["errin"], prev_net["errin"], dt
                    ),
                    "errout_per_sec": self._calculate_rate(  # 发送错误速度(errors/s)
                        current_net_stats["errout"], prev_net["errout"], dt
                    ),
                    "dropin_per_sec": self._calculate_rate(  # 接收丢包速度(drops/s)
                        current_net_stats["dropin"], prev_net["dropin"], dt
                    ),
                    "dropout_per_sec": self._calculate_rate(  # 发送丢包速度(drops/s)
                        current_net_stats["dropout"], prev_net["dropout"], dt
                    ),
                    # 常用的速度单位转换
                    "download_speed_mbps": bytes_recv_per_sec / 1024 / 1024 if bytes_recv_per_sec else None,
                    # 下载速度(MB/s)
                    "upload_speed_mbps": bytes_sent_per_sec / 1024 / 1024 if bytes_sent_per_sec else None,  # 上传速度(MB/s)
                    "download_speed_kbps": bytes_recv_per_sec / 1024 if bytes_recv_per_sec else None,  # 下载速度(KB/s)
                    "upload_speed_kbps": bytes_sent_per_sec / 1024 if bytes_sent_per_sec else None,  # 上传速度(KB/s)
                }

            # 更新历史数据
            self._prev_stats['network'] = current_net_stats.copy()

            network_info = {
                "cumulative": current_net_stats,  # 累计值
                "rates": net_rates,  # 变化率(/s)
            }
        else:
            network_info = {
                "cumulative": None,
                "rates": {}
            }

        self.dynamic_info_map['network'] = network_info

    def get_system_dynamic_info(self):
        """获取系统动态信息"""
        # 进程信息
        process_info = {
            "total_processes": len(psutil.pids()),  # 总进程数
            "running_processes": len([p for p in psutil.process_iter(['status'])
                                      if p.info['status'] == psutil.STATUS_RUNNING]),  # 运行中进程数
        }

        # 系统启动时间
        boot_time = psutil.boot_time()
        boot_time_info = {
            "boot_time": datetime.fromtimestamp(boot_time).isoformat(),  # 系统启动时间
            "uptime_seconds": time.time() - boot_time,  # 运行时间(秒)
        }

        system_info = {
            "processes": process_info,
            "boot_time": boot_time_info,
        }

        self.dynamic_info_map['system'] = system_info

    def collect_all(self):
        """采集所有动态信息"""
        print("正在采集系统动态信息...")

        timestamp = time.time()

        # 更新时间戳用于计算变化率
        self._prev_stats['timestamp'] = timestamp

        self.get_cpu_dynamic_info(timestamp)
        self.get_memory_dynamic_info()
        self.get_disk_dynamic_info(timestamp)
        self.get_network_dynamic_info(timestamp)
        self.get_system_dynamic_info()

        # 添加采集时间戳
        self.dynamic_info_map['collection_timestamp'] = datetime.fromtimestamp(timestamp).isoformat()

        print("动态信息采集完成！")

    def p_info(self):
        """输出采集的动态信息"""
        return self.dynamic_info_map

    def get_summary_info(self):
        """获取摘要信息（常用的关键指标）"""
        summary = {}

        # CPU摘要
        if 'cpu' in self.dynamic_info_map:
            cpu_data = self.dynamic_info_map['cpu']
            summary['cpu'] = {
                "usage_percent": cpu_data.get('usage', {}).get('cpu_percent'),
                "load_average": cpu_data.get('usage', {}).get('load_average'),
                "frequency_mhz": cpu_data.get('frequency', {}).get('current'),
            }

        # 内存摘要
        if 'memory' in self.dynamic_info_map:
            mem_data = self.dynamic_info_map['memory']
            virtual = mem_data.get('virtual', {})
            swap = mem_data.get('swap', {})
            summary['memory'] = {
                "usage_percent": virtual.get('percent'),
                "available_gb": virtual.get('available', 0) / 1024 / 1024 / 1024 if virtual.get('available') else None,
                "swap_usage_percent": swap.get('percent'),
            }

        # 磁盘摘要
        if 'disk' in self.dynamic_info_map:
            disk_data = self.dynamic_info_map['disk']
            io_rates = disk_data.get('io', {}).get('rates', {})
            usage_data = disk_data.get('usage', {})

            summary['disk'] = {
                "usage_percent": usage_data.get('usage_percent'),  # 磁盘使用百分比
                "free_space_gb": usage_data.get('free_space', 0) / 1024 / 1024 / 1024 if usage_data.get(
                    'free_space') else None,  # 剩余空间(GB)
                "total_space_gb": usage_data.get('total_space', 0) / 1024 / 1024 / 1024 if usage_data.get(
                    'total_space') else None,  # 总空间(GB)
                "read_speed_mbps": io_rates.get('read_speed_mbps'),  # 读速度(MB/s)
                "write_speed_mbps": io_rates.get('write_speed_mbps'),  # 写速度(MB/s)
                "read_iops": io_rates.get('read_iops'),  # 读IOPS
                "write_iops": io_rates.get('write_iops'),  # 写IOPS
            }

        # 网络摘要
        if 'network' in self.dynamic_info_map:
            net_data = self.dynamic_info_map['network']
            net_rates = net_data.get('rates', {})
            net_cumulative = net_data.get('cumulative', {})
            summary['network'] = {
                "download_speed_mbps": net_rates.get('download_speed_mbps'),      # 下载速度(MB/s)
                "upload_speed_mbps": net_rates.get('upload_speed_mbps'),          # 上传速度(MB/s)
                "packets_recv_per_sec": net_rates.get('packets_recv_per_sec'),    # 接收包速度(packets/s)
                "packets_sent_per_sec": net_rates.get('packets_sent_per_sec'),    # 发送包速度(packets/s)
                "total_bytes_recv": net_cumulative.get('bytes_recv'),             # 总接收字节数
                "total_bytes_sent": net_cumulative.get('bytes_sent'),             # 总发送字节数
            }

        return summary

    def p_summary_info(self):
        """输出摘要信息"""
        summary = self.get_summary_info()
        return summary


# # 使用示例
# if __name__ == "__main__":
#     # 创建采集器
#     collector = DeviceDynamicCollector()
#
#     # 第一次采集（用于初始化历史数据）
#     collector.collect_all()
#
#     # 等待一段时间再次采集（这样就能计算变化率了）
#     print("\n等待5秒后进行第二次采集以计算变化率...")
#     time.sleep(5)
#
#     # 第二次采集
#     collector.collect_all()
#
#     # 输出完整信息
#     print("\n=== 完整动态信息 ===")
#     collector.p_info()
#
#     # 输出摘要信息
#     print("\n=== 摘要信息 ===")
#     collector.p_summary_info()
